package com.ky.manage.utils.log;

import android.os.Environment;
import android.os.Process;

import com.ky.manage.utils.FileUtil;
import com.ky.manage.utils.TimeUtil;
import com.ky.manage.utils.threadpool.ThreadPoolUtils;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * 日志记录工具类： 参考https://github.com/Jesse505/AwesomeLog
 * @author zhaoyan
 * @date 2020-01-15
 */
public class StaticLogUtil {
    private static final String TAG = StaticLogUtil.class.getSimpleName();
    private static volatile StaticLogUtil instance = null;
    /**
     * 日志队列
     */
    public static final int QUEUE_LOG_CAPACITY = 2048;
    /**
     * 日志队列
     */
    private ArrayBlockingQueue<byte[]> mLogInfoQueue = new ArrayBlockingQueue<>(QUEUE_LOG_CAPACITY);
    /**
     * log目录
     */
    private String mLogPath;
    /**
     * 日志队列满日志
     */
    private static final String QUEUE_FULL_INFO = "埋点日志队列满！\n";
    /**
     * 日志文件输出流
     */
    private volatile FileOutputStream mLogFileOutputStream;

    private StaticLogUtil() {
        initFileOutputStream();
        startSaveLogThread();
    }

    /**
     * 启动保存日志线程
     */
    public void startSaveLogThread() {
        logInfo("startSaveLogThread", "启动保存埋点日志线程");
        ThreadPoolUtils.getInstance().executeCoreJob("static_info_thread", 0, ()->{
            //日志存储线程
            while (true) {
                synchronized (this) {
                    try {
                        if (null != mLogInfoQueue && mLogInfoQueue.size() > 0) {
                            byte[] logInfo = mLogInfoQueue.poll();
                            if (null != logInfo && logInfo.length > 0) {
                                writeLogInfo2File(logInfo);
                            } else {
                                try {
                                    Thread.sleep(5);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                        } else {
                            try {
                                Thread.sleep(5);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    } catch (Exception e) {
                        logInfo("startSaveLogThread", "e = " + e.toString());
                        if (e instanceof InterruptedException) {
                            //重启线程
                            startSaveLogThread();
                            break;
                        }
                    }
                }
            }
            closeFileOutputStream();
        }, null);
    }

    public static StaticLogUtil getInstance() {
        if (instance == null) {
            synchronized (StaticLogUtil.class) {
                if (instance == null) {
                    instance = new StaticLogUtil();
                }
            }
        }
        return instance;
    }

    private void initFileOutputStream() {
        if (mLogFileOutputStream == null) {
            String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();
            mLogPath = sdPath + "/zyStatisticInfo/";
            String date = TimeUtil.getStatisticDate(System.currentTimeMillis());
            String logFileName = "zy_statistic_" + date + ".txt";
            String fileNameWithPath = FileUtil.createMkdirsFile(mLogPath, logFileName);
            try {
                mLogFileOutputStream = new FileOutputStream(fileNameWithPath, true);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 记录埋点信息
     * @param tag
     * @param param
     */
    public void logInfo(String tag, String... param) {
        //信息拼接
        StringBuffer statisticInfo = new StringBuffer();
        statisticInfo.setLength(0);
        statisticInfo.append(TimeUtil.getAllDate(System.currentTimeMillis()))
                .append(" ")
                .append("Pid ")
                .append(Process.myPid())
                .append("_")
                .append(tag);
        for (String str : param) {
            statisticInfo.append("_").append(str);
        }
        statisticInfo.append("\n");
        byte[] logBytes = statisticInfo.toString().getBytes();
        boolean insertSuccess = mLogInfoQueue.offer(logBytes);
        if (!insertSuccess) {
            mLogInfoQueue.clear();
            mLogInfoQueue.offer(QUEUE_FULL_INFO.getBytes());
            mLogInfoQueue.offer(logBytes);
        }
    }

    /**
     * 保存日志到文件
     * @param info
     */
    private void writeLogInfo2File(byte[] info) {
        try {
            //一次启动记录一次
            initFileOutputStream();
            if (null != mLogFileOutputStream) {
                mLogFileOutputStream.write(info);
                mLogFileOutputStream.flush();
                mLogFileOutputStream.getFD().sync();
            }
        } catch (Exception e) {
            logInfo("writeLogInfo2File", "e = " + e.toString());
            closeFileOutputStream();
        }
    }

    public void closeFileOutputStream() {
        if (null != mLogFileOutputStream) {
            try {
                mLogFileOutputStream.close();
            } catch (Exception e) {
                logInfo("closeFileOutputStream", "e = " + e.toString());
            }
            mLogFileOutputStream = null;
        }
    }
}
